/********************************************************************************
 * Project Name		[JavaSE_Fundamentals]
 * File Name     	[ObjectCopy.java]
 * Creation Date 	[2015-01-01]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ********************************************************************************/
package reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Objects;

/**
 * 反射 - 对象拷贝
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 * 
 */
public class ObjectCopy {

	/**
	 * 对象拷贝方法
	 * 
	 * @param object
	 *            待拷贝的对象
	 * @return 拷贝生成的对象
	 * @throws Exception
	 */
	public static Object copyObject(Object object) throws Exception {
		Object copiedObject = null;
		// 获得对象所属的Class类型
		Class<?> classType = object.getClass();
		// 构造新的对象
		copiedObject = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});

		// 获得所有的属性(包括私有属性)
		Field[] fields = classType.getDeclaredFields();
		for (Field field : fields) {
			String fieldName = field.getName();
			String firstLetter = fieldName.substring(0, 1).toUpperCase();

			// 构建getters/setters方法名
			String gettersName = "get" + firstLetter + fieldName.substring(1);
			String settersName = "set" + firstLetter + fieldName.substring(1);

			// 构建getters/setters方法
			Method gettersMethod = classType.getMethod(gettersName);
			Method settersMethod = classType.getMethod(settersName, field.getType());

			// 调用getters/setters方法
			Object fieldValue = gettersMethod.invoke(object);// 从原始对象中获得属性值
			settersMethod.invoke(copiedObject, fieldValue);// 将值设置到新的对象中
		}

		return copiedObject;
	}

	public static void main(String[] args) throws Exception {
		Employee employee = new Employee();
		employee.setEmployeeId(1000001);
		employee.setName("Sean Yang");
		employee.setHireDate(new Date());
		System.out.println(employee);

		Employee copied = (Employee) copyObject(employee);
		if (employee.equals(copied)) {
			System.out.println(copied);
		}
	}
}

/**
 * 测试类
 * 
 * @author 不落的太阳(Sean Yang aka ShortPeace)
 * @version 1.0
 * @since jdk 1.8
 *
 */
class Employee {

	private long employeeId;
	private String name;
	private Date hireDate;

	public Employee() {
		super();
	}

	public Employee(long employeeId, String name, Date hireDate) {
		super();
		this.employeeId = employeeId;
		this.name = name;
		this.hireDate = hireDate;
	}

	public long getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(long employeeId) {
		this.employeeId = employeeId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Date getHireDate() {
		return hireDate;
	}

	public void setHireDate(Date hireDate) {
		this.hireDate = hireDate;
	}

	@Override
	public int hashCode() {
		return Objects.hash(this.employeeId, this.name, this.hireDate);
	}

	/**
	 * equals方法
	 * 
	 * @param obj
	 * @return equals比较结果
	 */
	@Override
	public boolean equals(Object obj) {
		return Objects.equals(this.employeeId, ((Employee) obj).employeeId)
				&& Objects.equals(this.name, ((Employee) obj).name)
				&& Objects.equals(this.hireDate, ((Employee) obj).hireDate);
	}

	/**
	 * toString方法
	 * 
	 * @return Employee的字符串表示
	 */
	@Override
	public String toString() {
		return "Employee [getEmployeeId()=" + getEmployeeId() + ", getName()=" + getName() + ", getHireDate()="
				+ getHireDate() + ", hashCode()=" + hashCode() + "]";
	}
}
